package com.lyEducation.util.controllerUtil;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import java.io.IOException;
import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ControllerUtil {
  private static ObjectMapper objectMapper = new ObjectMapper();
  private static JsonFactory jsonFactory = new JsonFactory();

  public static String getJSONString(Map<?, ?> map) {
    ObjectMapper objectMapper = new ObjectMapper();
    String jsonString = null;

    try {
      jsonString = objectMapper.writeValueAsString(map);
      System.out.println(jsonString);
      return jsonString;
    } catch (JsonGenerationException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (JsonMappingException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return jsonString;
  }

  public static String getJSONString(List<?> list) {
    ObjectMapper objectMapper = new ObjectMapper();
    String jsonString = null;

    try {
      jsonString = objectMapper.writeValueAsString(list);
      System.out.println(jsonString);
      return jsonString;
    } catch (JsonGenerationException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (JsonMappingException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return jsonString;
  }

  public static String getJSONString(Object object) {
    ObjectMapper objectMapper = new ObjectMapper();
    String jsonString = null;

    try {
      jsonString = objectMapper.writeValueAsString(object);
      System.out.println(jsonString);
      return jsonString;
    } catch (JsonGenerationException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (JsonMappingException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
    return jsonString;
  }

  /**
   * Object对象转json 2015年4月3日上午10:41:53 auther:shijing
   *
   * @param pojo
   * @return
   * @throws JsonMappingException
   * @throws JsonGenerationException
   * @throws IOException
   */
  public static String toJson(Object pojo)
      throws JsonMappingException, JsonGenerationException, IOException {
    return toJson(pojo, false);
  }

  public static String toJson(Object pojo, boolean prettyPrint)
      throws JsonMappingException, JsonGenerationException, IOException {
    StringWriter sw = new StringWriter();
    JsonGenerator jg = jsonFactory.createJsonGenerator(sw);
    if (prettyPrint) {
      jg.useDefaultPrettyPrinter();
    }
    objectMapper.writeValue(jg, pojo);
    return sw.toString();
  }

  /**
   * 获取某个月最后的一天
   *
   * @param year
   * @param month
   * @return
   */
  public static int getLastMonthDay(int year, int month) {
    if (year < 1 || month < 0 || month > 11) return -1;
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
    Calendar ca = Calendar.getInstance();
    ca.set(Calendar.YEAR, year);
    ca.set(Calendar.MONTH, month);
    // getActualMaximum()是获取给定日历字段的可能最大值
    ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
    String last = format.format(ca.getTime());
    System.out.println("===============last:" + last);
    return ca.get(Calendar.DAY_OF_MONTH);
  }

  //省(直辖市)码表
  private static String provinceCode[] = {"11", "12", "13", "14", "15", "21", "22",
          "23", "31", "32", "33", "34", "35", "36", "37", "41", "42", "43",
          "44", "45", "46", "50", "51", "52", "53", "54", "61", "62", "63",
          "64", "65", "71", "81", "82", "91"};
  //身份证前17位每位加权因子
  private static int[] power = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};

  //身份证第18位校检码
  private static String[] refNumber = {"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"};


  /**
   * 二代身份证号码有效性校验
   *
   * @param idNo
   * @return
   */
  public static boolean isValidIdNo(String idNo) {
    return isIdNoPattern(idNo) && isValidProvinceId(idNo.substring(0, 2))
            && isValidDate(idNo.substring(6, 14)) && checkIdNoLastNum(idNo);
  }

  /**
   * 检查身份证的省份信息是否正确
   *
   * @param provinceId
   * @return
   */
  public static boolean isValidProvinceId(String provinceId) {
    for (String id : provinceCode) {
      if (id.equals(provinceId)) {
        return true;
      }
    }
    return false;
  }


  /**
   * 二代身份证正则表达式
   *
   * @param idNo
   * @return
   */
  private static boolean isIdNoPattern(String idNo) {
    return Pattern.matches("^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}([\\d|x|X]{1})$", idNo);
  }

  /**
   * 判断日期是否有效
   *
   * @param inDate
   * @return
   */
  public static boolean isValidDate(String inDate) {
    if (inDate == null) {
      return false;
    }
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
    if (inDate.trim().length() != dateFormat.toPattern().length()) {
      return false;
    }
    dateFormat.setLenient(false);//执行严格的日期匹配
    try {
      dateFormat.parse(inDate.trim());
    } catch (ParseException e) {
      return false;
    }
    return true;
  }

  /**
   * 计算身份证的第十八位校验码
   *
   * @param cardIdArray
   * @return
   */
  public static String sumPower(int[] cardIdArray) {
    int result = 0;
    for (int i = 0; i < power.length; i++) {
      result += power[i] * cardIdArray[i];
    }
    return refNumber[(result % 11)];
  }

  /**
   * 校验身份证第18位是否正确(只适合18位身份证)
   *
   * @param idNo
   * @return
   */
  public static boolean checkIdNoLastNum(String idNo) {
    if (idNo.length() != 18) {
      return false;
    }
    char[] tmp = idNo.toCharArray();
    int[] cardidArray = new int[tmp.length - 1];
    int i = 0;
    for (i = 0; i < tmp.length - 1; i++) {
      cardidArray[i] = Integer.parseInt(tmp[i] + "");
    }
    String checkCode = sumPower(cardidArray);
    String lastNum = tmp[tmp.length - 1] + "";
    if (lastNum.equals("x")) {
      lastNum = lastNum.toUpperCase();
    }
    if (!checkCode.equals(lastNum)) {
      return false;
    }
    return true;
  }

  public static boolean isMobileNO(String mobile) {
    if (mobile.length() != 11) {
      return false;
    } else {
      /** 移动号段正则表达式 */
      String pat1 = "^((13[4-9])|(147)|(15[0-2,7-9])|(178)|(18[2-4,7-8]))\\d{8}|(1705)\\d{7}$";
      /** 联通号段正则表达式 */
      String pat2 = "^((13[0-2])|(145)|(15[5-6])|(176)|(18[5,6]))\\d{8}|(1709)\\d{7}$";
      /** 电信号段正则表达式 */
      String pat3 = "^((133)|(153)|(17[3,7])|(18[0,1,9])|(149)|(199))\\d{8}$";
      /** 虚拟运营商正则表达式 */
      String pat4 = "^((170))\\d{8}|(1718)|(1719)\\d{7}$";

      Pattern pattern1 = Pattern.compile(pat1);
      Matcher match1 = pattern1.matcher(mobile);
      boolean isMatch1 = match1.matches();
      if (isMatch1) {
        return true;
      }
      Pattern pattern2 = Pattern.compile(pat2);
      Matcher match2 = pattern2.matcher(mobile);
      boolean isMatch2 = match2.matches();
      if (isMatch2) {
        return true;
      }
      Pattern pattern3 = Pattern.compile(pat3);
      Matcher match3 = pattern3.matcher(mobile);
      boolean isMatch3 = match3.matches();
      if (isMatch3) {
        return true;
      }
      Pattern pattern4 = Pattern.compile(pat4);
      Matcher match4 = pattern4.matcher(mobile);
      boolean isMatch4 = match4.matches();
      if (isMatch4) {
        return true;
      }
      return false;
    }
  }


  public static boolean isMailNo(String mailNo) {
    Pattern pattern =
        Pattern.compile(
            "^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$");

    Matcher matcher = pattern.matcher(mailNo);
    return matcher.matches();
  }

  /**
   * 验证手机号码（支持国际格式，+86135xxxx...（中国内地），+00852137xxxx...（中国香港））
   *
   * @param mobile 移动、联通、电信运营商的号码段
   *     <p>移动的号段：134(0-8)、135、136、137、138、139、147（预计用于TD上网卡）
   *     、150、151、152、157（TD专用）、158、159、187（未启用）、188（TD专用）
   *     <p>联通的号段：130、131、132、155、156（世界风专用）、185（未启用）、186（3g）
   *     <p>电信的号段：133、153、180（未启用）、189
   * @return 验证成功返回true，验证失败返回false
   */
  public static boolean checkMobile(String mobile) {
    String regex = "(\\+\\d+)?1[3458]\\d{9}$";
    return Pattern.matches(regex, mobile);
  }
  //
  //  /**
  //   * 验证不必要的号码
  //   *
  //   * @param mobile
  //   * @return
  //   */
  //  public static boolean checkUnNeedTel(String mobile) {
  //    return UNNEEDTEL.contains(mobile) || mobile.startsWith("400");
  //  }

  /**
   * 验证固定电话号码
   *
   * @param phone 电话号码，格式：国家（地区）电话代码 + 区号（城市代码） + 电话号码，如：+8602085588447
   *     <p><b>国家（地区） 代码 ：</b>标识电话号码的国家（地区）的标准国家（地区）代码。它包含从 0 到 9 的一位或多位数字， 数字之后是空格分隔的国家（地区）代码。
   *     <p><b>区号（城市代码）：</b>这可能包含一个或多个从 0 到 9 的数字，地区或城市代码放在圆括号—— 对不使用地区或城市代码的国家（地区），则省略该组件。
   *     <p><b>电话号码：</b>这包含从 0 到 9 的一个或多个数字
   * @return 验证成功返回true，验证失败返回false
   */
  public static boolean isPhoneNo(String phone) {
    String regex = "(\\+\\d+)?(\\d{3,4}\\-?)?\\d{7,8}$";
    return Pattern.matches(regex, phone);
  }
  //  /**
  //   * 包括固话和手机号
  //   *
  //   * @param str
  //   * @return 验证通过返回true
  //   */
  //  public static boolean isTelNumber(String str) {
  //    return checkMobile(str) && !checkUnNeedTel(str);
  //  }
}
